#include <stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdbool.h>

#define MAX_EPOLL_NUM 100
#define SERVER_PORT 8080
// #define SERVER_IP "192.168.252.130"
// #define SERVER_IP "123.249.105.151"
#define SERVER_IP "127.0.0.1"//服务器的IP
void print_menu();
int main(void)
{
    int ret;
    bool menu_show_flag = true;

    char stdin_buffer[BUFSIZ] = { 0 };
    char send_buffer[BUFSIZ] = { 0 };
    char recv_buffer[BUFSIZ] = { 0 };

    /*========<连接服务器逻辑>========*/
    int serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverfd < 0)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in serverSock;
    socklen_t serverLen = sizeof(serverSock);
    serverSock.sin_family = AF_INET;
    serverSock.sin_port = htons(SERVER_PORT);
    if (inet_pton(AF_INET, SERVER_IP, &serverSock.sin_addr) < 0)
    {
        perror("inet_pton");
        exit(EXIT_FAILURE);
    }

    ret = connect(serverfd, (struct sockaddr*)&serverSock, serverLen);
    if (ret < 0)
    {
        perror("connect");
        exit(EXIT_FAILURE);
    }

    /*========<epoll监听>========*/
    int ep = epoll_create1(0);
    struct epoll_event ev, events[MAX_EPOLL_NUM];

    ev.data.fd = STDIN_FILENO;
    ev.events = EPOLLIN;
    if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &ev) < 0)
    {
        perror("epoll_ctl ADD stdin");
        exit(EXIT_FAILURE);
    }
    ev.data.fd = serverfd;
    ev.events = EPOLLIN;
    if (epoll_ctl(ep, EPOLL_CTL_ADD, serverfd, &ev) < 0)
    {
        perror("epoll_ctl ADD serverfd");
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        if(menu_show_flag)//防止显示多次
            print_menu();
        
        int nfds = epoll_wait(ep, events, MAX_EPOLL_NUM, -1);

        for (int i = 0;i < nfds;i++)
        {
            if (events[i].data.fd == STDIN_FILENO)
            {
                memset(stdin_buffer, 0, sizeof(stdin_buffer));
                fgets(stdin_buffer, sizeof(stdin_buffer), stdin);

                int len = strlen(stdin_buffer);
                if (len > 0 && stdin_buffer[len - 1] == '\n')
                    stdin_buffer[len - 1] = '\0';

                if (strcmp(stdin_buffer, "0") == 0)
                {
                    close(serverfd);
                    close(ep);
                    return 0;
                }

                snprintf(send_buffer, sizeof(send_buffer), "%s", stdin_buffer);//此处之后可以加上stdin--->send的逻辑
                if (strlen(send_buffer) > 0)
                {
                    ret = send(serverfd, send_buffer, strlen(send_buffer), 0);
                    if (ret < 0)
                        perror("send");
                }

                menu_show_flag = false;
            }

            else if (events[i].data.fd == serverfd)
            {
                memset(recv_buffer, 0, sizeof(recv_buffer));
                ret = recv(serverfd, recv_buffer, sizeof(recv_buffer) - 1, 0);
                if (ret < 0)
                {
                    perror("recv");
                }
                else if (ret == 0)
                {
                    printf("服务器已关闭\n");
                    close(serverfd);
                    close(ep);
                    return 0;
                }
                else if (ret > 0)
                {
                    recv_buffer[ret] = '\0';
                    printf("[服务器]:%s\n", recv_buffer);
                }
                menu_show_flag = true;
            }
        }
    }
    close(serverfd);
    close(ep);
}


void print_menu()
{
    printf("\n====== 学生成绩管理系统 ======\n");
    printf("1. 创建数据表\t(1 <数据表名字>)\n");
    printf("2. 插入数据\t(2 <数据表名字> <ID> <名字> <性别> <成绩>)\n");
    printf("3. 删除数据\t(3 <数据表名字> <要删除的学生的姓名>)\n");
    printf("4. 更新成绩\t(4 <数据表名字> <要修改学生成绩的姓名> <新成绩>)\n");
    printf("5. 查询学生\t(5 <数据表名字> <要查找的学生的姓名>)\n");
    printf("0. 退出\n");
    printf("请输入操作编号: ");
    fflush(stdout);
}
